<template>
  <el-form
    ref="form"
    :model="form"
    :rules="rules"
    :inline="true"
    size="medium"
    :label-width="`${labelWidth}px`"
    label-position="right"
    :disabled="action === 'view'"
    :validate-on-rule-change="false"
  >
    <div v-for="(c,i) in config" :key="`form-group-${i}`" class="b-form-group">
      <el-divider content-position="left">{{ c.title }}</el-divider>
      <div class="p-20">
        <slot v-if="c.type === 'custom'" :name="c.name" :form="form" />
        <el-row v-else-if="c.type === 'form'">
          <el-col v-for="(item, j) in c.children" :key="`form-item-${j}`" :span="setSpan(item)">
            <el-form-item v-if="!item.ignore" :label="item.label" :prop="item.key" class="b-form-item">
              <slot v-if="item.type === 'custom'" :name="item.name" :form="form" />
              <el-input
                v-else-if="item.type === 'input'"
                v-model="form[item.key]"
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :style="`width: ${item.width || '100%'}`"
                :disabled="item.disabled"
                type="input"
                clearable
              >
                <template v-if="item.prepend" slot="prepend">{{ item.prepend }}</template>
                <template v-if="item.append" slot="append">{{ item.append }}</template>
              </el-input>
              <el-input-number
                v-else-if="item.type === 'input-number'"
                v-model="form[item.key]"
                controls-position="right"
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :style="`width: ${item.width || '100%'}`"
                :min="item.min"
                :max="item.max"
                :disabled="item.disabled"
              />
              <el-input
                v-else-if="item.type === 'password'"
                v-model="form[item.key]"
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :style="`width: ${item.width || '100%'};`"
                autocomplete="new-password"
                type="password"
                :disabled="item.disabled"
                clearable
              />
              <el-input
                v-else-if="item.type === 'textarea'"
                v-model="form[item.key]"
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :style="`width: ${item.width || '100%'};`"
                type="textarea"
                :rows="item.rows ? item.rows : 2"
                :disabled="item.disabled"
                clearable
              />
              <el-select
                v-else-if="item.type === 'select'"
                v-model="form[item.key]"
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :style="`width: ${item.width || '100%'}`"
                :disabled="item.disabled"
                :multiple="item.multiple"
                :filterable="setSelectFilterable(item.filterable)"
                clearable
              >
                <template v-if="tagDataType(item.data) === 'array'">
                  <el-option v-for="dict in item.data" :key="`${item.label}-${dict.value}`" :label="dict.label" :value="dict.value" />
                </template>
                <template v-if="tagDataType(item.data) === 'object'">
                  <el-option
                    v-for="dict in item.data.data"
                    :key="`${dict[item.data.label || 'label']}-${dict[item.data.value || 'value']}`"
                    :label="dict[item.data.label || 'label']"
                    :value="dict[item.data.value || 'value']"
                  />
                </template>
              </el-select>
              <el-radio-group v-else-if="item.type === 'radio'" v-model="form[item.key]" :style="`width: ${item.width || '100%'}`" :disabled="item.disabled">
                <template v-if="tagDataType(item.data) === 'array'">
                  <el-radio v-for="dict in item.data" :key="`${dict.label}-${dict.value}`" :label="dict.value">{{ dict.label }}</el-radio>
                </template>
                <template v-if="tagDataType(item.data) === 'object'">
                  <el-radio
                    v-for="dict in item.data.data"
                    :key="`${dict[item.data.label || 'label']}-${dict[item.data.value || 'value']}`"
                    :label="dict[item.data.value || 'value']"
                  >{{ dict[item.data.label || 'label'] }}</el-radio>
                </template>
              </el-radio-group>
              <el-radio-group
                v-else-if="item.type === 'radio-button'"
                v-model="form[item.key]"
                :style="`width: ${item.width || '100%'}`"
                :disabled="item.disabled"
              >
                <template v-if="tagDataType(item.data) === 'array'">
                  <el-radio-button v-for="dict in item.data" :key="`${dict.label}-${dict.value}`" :label="dict.value">{{ dict.label }}</el-radio-button>
                </template>
                <template v-if="tagDataType(item.data) === 'object'">
                  <el-radio-button
                    v-for="dict in item.data.data"
                    :key="`${dict[item.data.label || 'label']}-${dict[item.data.value || 'value']}`"
                    :label="dict[item.data.value || 'value']"
                  >{{ dict[item.data.label || 'label'] }}</el-radio-button>
                </template>
              </el-radio-group>
              <el-date-picker
                v-else-if="item.type === 'date' || item.type ==='week' || item.type ==='month' || item.type ==='year' || item.type ==='datetime'"
                v-model="form[item.key]"
                :type="item.type"
                :style="`width: ${item.width || '100%'}`"
                clearable
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :disabled="item.disabled"
                :format="item.format"
                :value-format="item.valueFormat"
              />
              <el-date-picker
                v-else-if="item.type === 'daterange' || item.type === 'datetimerange'"
                v-model="form[item.key]"
                :type="item.type"
                :style="`width: ${item.width || '100%'}`"
                clearable
                unlink-panels
                range-separator="至"
                :start-placeholder="action !== 'view' ? '开始日期': ''"
                :end-placeholder="action !== 'view' ? '结束日期' : ''"
                :disabled="item.disabled"
                :format="item.format"
                :value-format="item.valueFormat"
              />
              <el-time-picker
                v-else-if="item.type === 'time'"
                v-model="form[item.key]"
                :type="item.type"
                :style="`width: ${item.width || '100%'}`"
                clearable
                :placeholder="action !== 'view' ? item.placeholder : ''"
                :disabled="item.disabled"
                :format="item.format"
                :value-format="item.valueFormat"
              />
              <el-time-picker
                v-else-if="item.type === 'timerange'"
                v-model="form[item.key]"
                is-range
                :type="item.type"
                :style="`width: ${item.width || '100%'}`"
                clearable
                range-separator="至"
                :start-placeholder="action !== 'view' ? '开始时间': ''"
                :end-placeholder="action !== 'view' ? '结束时间' : ''"
                :disabled="item.disabled"
                :format="item.format"
                :value-format="item.valueFormat"
              />
              <VFileUpload
                v-else-if="item.type === 'fileUpload'"
                v-model="form[item.key]"
                :limit="item.limit"
                :file-size="item.fileSize"
                :file-type="item.fileType"
                :disabled="item.disabled"
              />
              <VImageUpload
                v-else-if="item.type === 'imageUpload'"
                v-model="form[item.key]"
                :limit="item.limit"
                :file-size="item.fileSize"
                :file-type="item.fileType"
                :disabled="item.disabled"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </div>
    </div>
  </el-form>
</template>

<script>
/**
 * V7 表单组件
 */
export default {
  name: 'VForm',
  props: {
    config: {
      type: Array,
      default() {
        return []
      }
    },
    columns: {
      type: Number,
      default: 2,
      validator(v) {
        return [1, 2, 3, 4, 6, 8, 12, 24].includes(v)
      }
    },
    labelWidth: {
      type: Number,
      default: 100
    },
    action: {
      type: String,
      default: 'add'
    },
    object: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      form: {}
    }
  },
  computed: {
    rules() {
      const resultRules = {}
      _.forEach(this.config, (c) => {
        if (c.children) {
          _.forEach(c.children, (cc) => {
            if (cc.rule) {
              resultRules[cc.key] = cc.rule
            }
          })
        }
      })
      return resultRules
    }
  },
  watch: {
    object: {
      handler() {
        this.loadData()
      },
      immediate: true
    }
  },
  created() {},
  mounted() {},
  methods: {
    // 编辑/查看时加载数据
    loadData() {
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.resetFields()
          this.form = {
            ...this.object
          }
        }
      })
    },
    // 设置搜索块的span占比
    setSpan(item) {
      if (item.span && item.span > 0 && item.span <= this.columns) {
        return (item.span * 24) / this.columns
      } else return 24 / this.columns
    },
    // 设置下拉框搜索配置
    setSelectFilterable(filterable) {
      if (_.isUndefined(filterable)) return true
      return filterable
    },
    tagDataType(tagData) {
      if (tagData) {
        if (_.isArray(tagData)) {
          return 'array'
        } else if (_.isObject(tagData)) {
          return 'object'
        }
      }
      return undefined
    }
  }
}
</script>

<style lang="scss" scoped>
.b-form-group {
  border: 1px solid #dcdfe6;
  border-top: 0;
  margin-bottom: 20px;
  .el-divider--horizontal {
    margin: 8px 0;
  }

  .el-divider__text {
    font-weight: 700;
  }
}
</style>
